package com.example.demo.session.scheduler;


import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.AbstractValidatingSessionManager;
import org.apache.shiro.session.mgt.DefaultSessionKey;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.session.mgt.SessionValidationScheduler;
import org.apache.shiro.session.mgt.ValidatingSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;

import com.example.demo.service.SessionService;
import com.example.demo.service.impl.SessionServiceImpl;
import com.example.demo.util.SerializableUtils;

/**
 * 定时会话验证器,用于验证会话是否过期
 * <p>@author Henry.Y</p>
 * <p>@date 2019-08-30</p>
 */
public class MySessionValidationScheduler implements SessionValidationScheduler,Runnable{

	private SessionService sessionService= new SessionServiceImpl();      //
	
	private static final Logger logger= LoggerFactory.getLogger(MySessionValidationScheduler.class);
	                         
	ValidatingSessionManager sessionManager;
	
	private ScheduledExecutorService service;
	
	private long interval= DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
	
	private boolean enabled= false;
	
	public MySessionValidationScheduler(){
		super();
	}
	
	public void setSessionManager(ValidatingSessionManager sessionManager){
		this.sessionManager= sessionManager;
	}
	
	public ValidatingSessionManager getSessionManager(){
		
		return this.sessionManager;
	}
	
	public void setInterval(long interval){
		this.interval= interval;
	}
	
	public long getInterval(){
		
		return this.interval;
	} 
	
	public boolean isEnabled(){
		
		return this.enabled;
	}
	
	/** 
	 * 创建一个单独的线程{@link ScheduledExecutorService} 在固定的时间验证线程的有效性
	 * 之歌执行器或创建虚拟线程允许停止虚拟机
	 */
	public void enableSessionValidation(){
		if(this.interval>01){
			this.service= Executors.newSingleThreadScheduledExecutor(new ThreadFactory(){
				public Thread newThread(Runnable runnable){
					Thread thread= new Thread(runnable);
					thread.setDaemon(true);
					return thread;
				}
			});
			this.service.scheduleAtFixedRate(this, interval, interval, TimeUnit.MILLISECONDS);
			this.enabled= true;
		}
	}
	
	public void run(){
		
		if(logger.isDebugEnabled()){
			logger.debug("Executing session validation...");
		}
		/*if(logger.isInfoEnabled()){
			logger.info("Executing session validation...");
		}*/
		long stratTime= System.currentTimeMillis();
		com.example.demo.entity.Session sessionCEDM= new com.example.demo.entity.Session();
		int strat= 0;
		int size= 20;
		sessionCEDM.setStrat(strat);
		sessionCEDM.setLimit(size);
		List<String> sessionList=sessionService.selectSessionByLimit(sessionCEDM);
		System.out.println(sessionList.size());
		while(sessionList.size()>0){
			for(String sessionStr:sessionList){
				try{
					Session session= SerializableUtils.deserialize(sessionStr);
					Method validateMethod= ReflectionUtils.findMethod(AbstractValidatingSessionManager.class,"validate",Session.class,SessionKey.class);
					validateMethod.setAccessible(true);
					ReflectionUtils.invokeMethod(validateMethod, sessionManager,session, new DefaultSessionKey(session.getId()));
				}catch(Exception e){
					e.printStackTrace();
				}
			}
			strat= strat+size;
			sessionCEDM.setStrat(strat);
			System.out.println(sessionCEDM.toString());
			sessionList= sessionService.selectSessionByLimit(sessionCEDM);
		}
		long stopTime= System.currentTimeMillis();
		if(logger.isDebugEnabled()){
			logger.debug("Session validation completed successfully in "+ (stopTime - stratTime) + "milliseconds");
		}
	}
	
	public void disableSessionValidation(){
	    System.out.println("调用disableSessionValidation方法");
		this.service.shutdownNow();
		this.enabled= false;
	}
}
